package com.nulldev.util.net.irc.commands;

import java.util.HashSet;
import java.util.Set;

import com.nulldev.util.net.irc.Channel;
import com.nulldev.util.net.irc.Connection;
import com.nulldev.util.net.irc.Entity;
import com.nulldev.util.net.irc.Server;
import com.nulldev.util.net.irc.User;
import com.nulldev.util.net.irc.utils.IRCUtils;
import com.nulldev.util.threading.legacy.ThreadExecutor;

public class Mode implements Connection.CommandHandler {

	@Override
	public boolean applies(Connection connection, String command, String line) {
		return command.equals("MODE");
	}

	@Override
	public void process(Connection connection, String line, String[] parts) {
		String _source = IRCUtils.parseSource(parts[0]), _target = parts[2], _mode = parts[3], __target2 = null;
		if (parts.length > 4) {
			__target2 = parts[4];
		}
		Server server = connection.getServer();
		User source = server.getUser(_source);
		final Entity target;
		if (_target.startsWith("#")) {
			target = server.getChannel(_target);
		} else {
			target = server.getUser(_target);
		}
		Entity _target2 = target;
		if (__target2 != null) {
			_target2 = server.getUser(__target2);
		}
		final Entity target2 = _target2;
		boolean add = _mode.charAt(0) == '+';
		Set<com.nulldev.util.net.irc.Mode> modes = new HashSet<com.nulldev.util.net.irc.Mode>();
		for (char ch : _mode.substring(1).toCharArray()) {
			modes.add(new com.nulldev.util.net.irc.Mode(source, _target2, IRCUtils.getTimestamp(), com.nulldev.util.net.irc.Mode.Type.fromChar(ch, target instanceof User ? com.nulldev.util.net.irc.Mode.Type.Context.USER : (_target2 instanceof User ? com.nulldev.util.net.irc.Mode.Type.Context.CHANNEL_USER : com.nulldev.util.net.irc.Mode.Type.Context.CHANNEL))));
		}
		if (target instanceof Channel && _target2 instanceof User) {
			for (final com.nulldev.util.net.irc.Mode mode : modes) {
				if (add) {
					ThreadExecutor.execute(new Runnable() {
						@Override
						public void run() {
							((User) target2).addChannelRank((Channel) target, mode.getType());
						}
					});
				} else {
					ThreadExecutor.execute(new Runnable() {
						@Override
						public void run() {
							((User) target2).removeChannelRank((Channel) target, mode.getType());
						}
					});
				}
			}
		}
		connection.getCallback().onMode(connection, target, modes, add);
	}

}
